package ordersubmit

import (
	"context"
	"runtime"

	"mall/service/forum/api/internal/biz/promotion"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/product/rpc/productclient"
	"mall/service/promotion/rpc/promotionclient"

	"github.com/shopspring/decimal"
	"github.com/zeromicro/go-zero/core/logx"
)

type Modifier struct {
	ActivityId       int64           ///
	RuleId           int64           ///
	CouponId         int64           ///
	CouponTemplateId int64           ///
	ActivityAmount   decimal.Decimal ///
	CouponAmount     decimal.Decimal ///
	Status           int             //
	Effect           uint32
	EffectType       uint32
	EffectValue      string
}

// Context Context
type Context struct {
	Req            *types.CreateOrderReq //
	Resp           *types.CheckoutInfo   //
	Ctx            context.Context       //
	SvcCtx         *svc.ServiceContext   //
	UserId         uint64                //
	UserRank       string                //
	UserName       string                //
	UserOpenId     string                //
	OrderType      uint32                //
	PaymentType    uint32                //
	Stocks         []*productclient.ProductVariationStock
	SkuScopeInfos  []*promotionclient.SkuScopeInfo
	PricingInfos   []*promotion.PricingInfo
	GemRatio       decimal.Decimal //
	AccountGems    decimal.Decimal //
	AccountPoint   uint64
	SkuAmountMap   map[uint64]decimal.Decimal  //
	MutexMap       map[uint32]map[uint64]int64 //
	SkusAmount     decimal.Decimal
	SkusNumber     int64
	SkusWeight     decimal.Decimal
	ActivityAmount decimal.Decimal
	CouponAmount   decimal.Decimal
	Freight        decimal.Decimal
	FinalFreight   decimal.Decimal
	FinalAmount    decimal.Decimal
	Modifiers      []*Modifier
}

// Handler 处理
type Handler interface {
	// 自身的业务
	Do(c *Context) error
	// 设置下一个对象
	SetNext(h Handler) Handler
	// 执行
	Run(c *Context) error
}

// Next 抽象出来的 可被合成复用的结构体
type Next struct {
	// 下一个对象
	nextHandler Handler
}

// SetNext 实现好的 可被复用的SetNext方法
// 返回值是下一个对象 方便写成链式代码优雅
// 例如 nullHandler.SetNext(argumentsHandler).SetNext(signHandler).SetNext(frequentHandler)
func (n *Next) SetNext(h Handler) Handler {
	n.nextHandler = h

	return h
}

// Run 执行
func (n *Next) Run(c *Context) (err error) {
	// 由于go无继承的概念 这里无法执行当前handler的Do
	// n.Do(c)
	if n.nextHandler != nil {
		// 合成复用下的变种
		// 执行下一个handler的Do
		if err = (n.nextHandler).Do(c); err != nil {
			return err
		}

		// 执行下一个handler的Run
		return (n.nextHandler).Run(c)
	}

	return
}

// NullHandler 空Handler
// 由于go无继承的概念 作为链式调用的第一个载体 设置实际的下一个对象
type NullHandler struct {
	// 合成复用Next的`nextHandler`成员属性、`SetNext`成员方法、`Run`成员方法
	Next
}

// Do 空Handler的Do
func (h *NullHandler) Do(c *Context) (err error) {
	// 空Handler 这里什么也不做 只是载体 do nothing...
	return
}

// CartInfoHandler 获取购物车数据handler
type CartInfoHandler struct {
	// 合成复用Next
	Next
}

// Do 获取购物车数据
func (h *CartInfoHandler) Do(c *Context) (err error) {
	logx.Infow("获取购物车数据...")

	return
}

// DBTableOrderHandler 写订单表handler
type DBTableOrderHandler struct {
	// 合成复用Next
	Next
}

// Do 写订单表
func (h *DBTableOrderHandler) Do(c *Context) (err error) {
	logx.Infow("写订单表...")

	return
}

// DBTableOrderSkusHandler 写订单商品表handler
type DBTableOrderSkusHandler struct {
	// 合成复用Next
	Next
}

// Do 校验参数的逻辑
func (h *DBTableOrderSkusHandler) Do(c *Context) (err error) {
	logx.Infow("写订单商品表...")

	return
}

// DBTableOrderPromotionsHandler 写订单优惠信息表handler
type DBTableOrderPromotionsHandler struct {
	// 合成复用Next
	Next
}

// Do 校验参数的逻辑
func (h *DBTableOrderPromotionsHandler) Do(c *Context) (err error) {
	logx.Infow("写订单优惠信息表...")

	return
}

// 获取正在运行的函数名
func runFuncName() string {
	pc := make([]uintptr, 1)
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])

	return f.Name()
}

func Demo() {
	// 初始化空handler
	nullHandler := &NullHandler{}

	// 链式调用 代码是不是很优雅
	// 很明显的链 逻辑关系一览无余
	nullHandler.SetNext(&ArgumentsHandler{}).
		SetNext(&AddressInfoHandler{}).
		SetNext(&CartInfoHandler{}).
		SetNext(&SkuInfoHandler{}).
		SetNext(&PromotionInfoHandler{}).
		SetNext(&PromotionUseHandler{}).
		SetNext(&CouponInfoHandler{}).
		SetNext(&CouponUseHandler{}).
		SetNext(&ShipmentInfoHandler{}).
		SetNext(&PackageAndCleanupHandler{})
		// SetNext(&StockSubtractHandler{}).
		// SetNext(&CartDelHandler{}).
		// SetNext(&DBTableOrderHandler{}).
		// SetNext(&DBTableOrderSkusHandler{}).
		// SetNext(&DBTableOrderPromotionsHandler{})
		// 无限扩展代码...

	// 开始执行业务
	if err := nullHandler.Run(&Context{}); err != nil {
		// 异常
		logx.Infow("Fail | Error:", logx.Field("detail", err.Error()))

		return
	}

	// 成功
	logx.Infow("Success")
}
